﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Threading;

namespace FileService
{
    public class FileFactory
    {
        static string fileServlet = "http://222.85.149.6:8089/BMFileService/FileServlet";
        static string versionUrl = "http://222.85.149.6:8089/BMFileService/VersionServlet";
        readonly static string root = "http://222.85.149.6:8089/BMFileService/";
        readonly static string backDownloadUrl = "http://222.85.149.6:8089/BMFileService/File/Back/";

        public delegate void UploadFileHandler(int percent, int speed, long sended, long Length);

        /// <summary>
        /// PC客户端下载路径
        /// </summary>
        public static string BackDownloadUrl
        {
            get { return backDownloadUrl; }
        }

        /// <summary>
        /// 数据服务根目录
        /// </summary>
        public static string Root
        {
            get { return root; }
        } 

        /// <summary>
        /// 下载
        /// </summary>
        /// <param name="URL"></param>
        /// <param name="Dir"></param>
        public static void Download(string URL , string Dir)
        {
            WebClient client = new WebClient();
            //监听进度
            //client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);
            //client.DownloadFileCompleted += new System.ComponentModel.AsyncCompletedEventHandler(client_DownloadFileCompleted);
            string fileName = URL.Substring(URL.LastIndexOf("/") + 1); //被下载的文件名
            if (!Directory.Exists(Dir))
            { Directory.CreateDirectory(Dir); }
            string Path = System.IO.Path.Combine(Dir, fileName);   //另存为的绝对路径＋文件名

            //try
            //{ WebRequest myre = WebRequest.Create(URL); }
            //catch { }

            try
            {
                client.DownloadFileAsync(new Uri(URL), Path);
                //client.DownloadFile(URL, Path);
            }
            catch { }
        }

        public static string GetUrl(string url, int folder)
        {
            return root + FolderEnum.getPathfrom(folder) + "\\" + url;
        }

        /// <summary>
        /// 上传文件，默认存放在temp文件夹中
        /// </summary>
        /// <param name="path"></param>
        /// <param name="ImageFolderEnum"></param>
        /// <returns></returns>
        public static string UploadFile(string path, string filename, int folder = FolderEnum.TEMP, UploadFileHandler handler=null)
        {
            string rt = null;
            //if (folder == FolderEnum.IMAGE)
            //{
            //    string suffix = path.Substring(path.LastIndexOf("."));
            //    filename += suffix;
            //}

            string Url = fileServlet + "?op=" + OPFileType.UPLOAD + "&&filename=" + filename + "&&tofolder=" + folder;

            if (UploadFile(Url, path, handler).Equals("true"))
            {
                rt = filename;
            }
            return rt;
        }

        public static bool FileOperate(int OPFileType,int fromfolder, string oldfilename, int tofolder, string newfilename)
        {
            string Url = fileServlet + "?op=" + OPFileType + "&&fromfolder=" + fromfolder + "&&oldfilename=" + oldfilename + "&&tofolder=" + tofolder + "&&newfilename=" + newfilename;
            return GetResultFrom(Url).ToLower().Equals("true");
        }

        public static bool Exist(int fromfolder, string filename)
        {
            string Url = fileServlet + "?op=" + OPFileType.EXIST + "&&fromfolder=" + fromfolder + "&&filename=" + filename;
            return GetResultFrom(Url).ToLower().Equals("true");
        }

        public static bool Delete(int fromfolder, string filename)
        {
            string Url = fileServlet + "?op=" + OPFileType.DELETE + "&&fromfolder=" + fromfolder + "&&filename=" + filename;
            return GetResultFrom(Url).ToLower().Equals("true");
        }

        public static string GetLastBackVersion()
        {
            string url = versionUrl + "?vstype=1";
            Uri uri = new Uri(url);
            WebRequest webrequest = WebRequest.Create(uri);
            webrequest.ContentType = "application/x-www-form-urlencoded";//发送表单 而text/html 发送流
            webrequest.Method = "POST";

            WebResponse webresponse = webrequest.GetResponse();
            using (StreamReader mystream = new StreamReader(webresponse.GetResponseStream()))
            {
                return mystream.ReadToEnd();
            }
        }

        public static string GetVersionTxt(string version)
        {
            string url = versionUrl + "?vstype=3&version="+version;
            Uri uri = new Uri(url);
            WebRequest webrequest = WebRequest.Create(uri);
            webrequest.ContentType = "application/x-www-form-urlencoded";//发送表单 而text/html 发送流
            webrequest.Method = "POST";

            WebResponse webresponse = webrequest.GetResponse();
            Encoding encode = Encoding.GetEncoding("UTF-8");
            using (StreamReader mystream = new StreamReader(webresponse.GetResponseStream(), encode))
            {
                return mystream.ReadToEnd();
            }
        }

        public static int transformVersion(string version)
        {
            string[] vers = version.Split('.');
            try
            {
                int ver1 = int.Parse(vers[0]);
                int ver2 = int.Parse(vers.Length > 1 ? vers[1] : "0");
                int ver3 = int.Parse(vers.Length > 2 ? vers[2] : "0");
                int ver4 = int.Parse(vers.Length > 3 ? vers[3] : "0");
                ver3 += ver4 / 256;
                ver4 %= 256;
                ver2 += ver4 / 256;
                ver3 %= 256;
                ver1 += ver4 / 256;
                ver2 %= 256;
                return (ver1 << 24) | (ver2 << 16) | (ver3 << 8) | (ver4);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
            return 0;
        }

        /// <summary>
        /// 上传文件到指定的url服务器
        /// </summary>
        /// <param name="url"></param>
        /// <param name="srcPath"></param>
        /// <returns></returns>
        private static string UploadFile(string url, string srcPath)
        {
            string rt = "false";

            string end = "\r\n";
            string twoHyphens = "--";
            string boundary = "******";

            Uri uri = new Uri(url);
            HttpWebRequest webrequest = (HttpWebRequest)WebRequest.Create(uri);
            webrequest.ContentType = "multipart/form-data;boundary=" + boundary;//发送表单 而text/html 发送流
            webrequest.Method = "POST";
            webrequest.KeepAlive = true;
            webrequest.Headers.Add("content", "text/html; charset=UTF-8");

            using (Stream requestStream = webrequest.GetRequestStream())
            {
                string str = twoHyphens + boundary + end;
                byte[] bytes = System.Text.Encoding.ASCII.GetBytes(str);
                requestStream.Write(bytes, 0, bytes.Length);

                str = "Content-Disposition: form-data; name=\"file\"; filename=\"" + srcPath.Substring(srcPath.LastIndexOf("/") + 1) + "\"" + end + end;
                bytes = System.Text.Encoding.ASCII.GetBytes(str);
                requestStream.Write(bytes, 0, bytes.Length);

                using (FileStream fs = new FileStream(srcPath, FileMode.Open))
                {
                    long filelenght = fs.Length;
                    long curlenght = 0;

                    byte[] buffer = new byte[8192]; // 8k
                    int count = 0;
                    while ((count = fs.Read(buffer, 0, buffer.Length)) != 0)
                    {
                        requestStream.Write(buffer, 0, count);
                        curlenght += count;
                    }
                }

                str = end + twoHyphens + boundary + twoHyphens + end;
                bytes = System.Text.Encoding.ASCII.GetBytes(str);
                requestStream.Write(bytes, 0, bytes.Length);
                requestStream.Flush();
            }


            WebResponse webresponse = webrequest.GetResponse();
            using (StreamReader mystream = new StreamReader(webresponse.GetResponseStream()))
            {
                rt = mystream.ReadToEnd();
            }

            return rt.Replace("\r", "").Replace("\n", "");
        }
        
        /// <summary>
        /// 上传文件到指定的url服务器
        /// </summary>
        /// <param name="url"></param>
        /// <param name="srcPath"></param>
        /// <returns></returns>
        private static string UploadFile(string url, string srcPath, UploadFileHandler handler)
        {
            FileInfo file = new FileInfo(srcPath);
            //判断文件无效
            if (!file.Exists)
            {
                throw new Exception("文件不存在！");
            }
            //上传文件
            bool IsSending = true;
            bool Exception = false;
            long totallong = file.Length;
            file = null;
            Thread.Sleep(100);
            if (handler != null)
            {
                new Thread(() =>
                {
                    // TODO Auto-generated method stub
                    long x = 0, y = 0;//x 时间点数 y进度走向
                    int speed = 50 * 1024;//50k
                    int interval = 100;//sleep 间隔
                    long LengthCur = 0,lastLengthCur = 0;
                    DateTime lasttime = DateTime.Now;
                    while (LengthCur < totallong * 0.95 && IsSending && !Exception)
                    {
                        y = y + (int)((1.0 - 1.0 * LengthCur / (totallong * 0.95)) * (speed / interval));
                        LengthCur = y;
                        x += 1;
                        {
                            long lspan = LengthCur - lastLengthCur;
                            TimeSpan span = DateTime.Now - lasttime;
                            lastLengthCur = LengthCur;
                            lasttime = DateTime.Now;
                            int dspeed = (int)(lspan / span.TotalSeconds);
                            int percent = (int)(100.0 * LengthCur / totallong);
                            handler(percent, dspeed, LengthCur, totallong);
                        }
                        Thread.Sleep(1000 / interval);
                    }
                    long dpercent = 0, start = LengthCur;
                    long LengthTotal = totallong - start;
                    while (LengthCur < LengthTotal && dpercent < 100)
                    {
                        dpercent += 5;
                        LengthCur = start + (long)(dpercent * LengthTotal / 100.0);
                        {
                            long lspan = LengthCur - lastLengthCur;
                            TimeSpan span = DateTime.Now - lasttime;
                            lastLengthCur = LengthCur;
                            lasttime = DateTime.Now;
                            int dspeed = (int)(lspan / span.TotalSeconds);
                            int percent = (int)(100.0 * LengthCur / totallong);
                            handler(percent, dspeed, LengthCur, totallong);
                        }
                        Thread.Sleep(100);
                    }
                    //如果已经上传完了还没标记演示完成直接通知完成
                    handler(100, 0, totallong, totallong);
                }).Start();
            }
            string ret = "";
            try
            {
                ret = UploadFile(url, srcPath);
                //标记完成
                IsSending = false;
            }
            catch (Exception ex)
            {
                Exception = true;
                IsSending = false;
                throw ex;
            }
            return ret;
        }

        private static string GetResultFrom(string url)
        {
            Uri uri = new Uri(url);
            WebRequest webrequest = WebRequest.Create(uri);
            webrequest.ContentType = "application/x-www-form-urlencoded";//发送表单 而text/html 发送流
            webrequest.Method = "POST";

            WebResponse webresponse = webrequest.GetResponse();
            using (StreamReader mystream = new StreamReader(webresponse.GetResponseStream()))
            {
                return mystream.ReadToEnd().Replace("\r", "").Replace("\n", "");
            }
        }
    }
}
